package game

import (
	"common/logs"
	"fmt"
	"github.com/fsnotify/fsnotify"
	"github.com/spf13/viper"
	"log"
	"os"
	"path"
)

var Conf *Config

const (
	gameConfig         = "gameConfig.json"
	servers            = "servers.json"
	starshipConfig     = "starshipConfig.json"
	buildConfig        = "buildConfig.json"
	materialConfig     = "materialConfig.json"
	resourceStarConfig = "resourceStarConfig.json"
	activityConfig     = "activityConfig.json"
)

type Config struct {
	GameConfig map[string]map[string]any `json:"gameConfig"`
	//GameConfig         map[string]ConfigValue `json:"gameConfig"`
	StarshipConfig     map[string]ConfigValue `json:"starshipConfig"`
	BuildConfig        map[string]ConfigValue `json:"buildConfig"`
	MaterialConfig     map[string]ConfigValue `json:"materialConfig"`
	ResourceStarConfig map[string]ConfigValue `json:"resourceStarConfig"`
	ActivityConfig     map[string]ConfigValue `json:"activityConfig"`
	ServersConf        ServersConf            `json:"serversConf"`
}
type ServersConf struct {
	Nats       NatsConfig         `json:"nats" `
	Connector  []*ConnectorConfig `json:"connector" `
	Servers    []*ServersConfig   `json:"servers" `
	TypeServer map[string][]*ServersConfig
}

type ServersConfig struct {
	ID               string `json:"id" `
	ServerType       string `json:"serverType" `
	HandleTimeOut    int    `json:"handleTimeOut" `
	RPCTimeOut       int    `json:"rpcTimeOut" `
	MaxRunRoutineNum int    `json:"maxRunRoutineNum" `
}

type ConnectorConfig struct {
	ID         string `json:"id" `
	Host       string `json:"host" `
	ClientPort int    `json:"clientPort" `
	Frontend   bool   `json:"frontend" `
	ServerType string `json:"serverType" `
}
type NatsConfig struct {
	//Url string `json:"url" mapstructure:"db"`
	Url string `json:"url"`
}

type ConfigValue struct {
	Value    map[string]Value `json:"value"`
	Describe string           `json:"describe"`
	Backend  bool             `json:"backend"`
}

type Value struct {
	Val      any          `json:"val"`
	Type     int          `json:"type"`
	For      map[int]uint `json:"for"`
	Describe string       `json:"describe"`
	Backend  bool         `json:"backend"`
}

type GameConfigValue struct {
	Value    map[string]any `json:"value"`
	Describe string         `json:"describe"`
	Backend  bool           `json:"backend"`
}

//type GameConfigValue map[string]any

func InitConfig(configDir string) {
	Conf = new(Config)
	dir, err := os.ReadDir(configDir)
	if err != nil {
		logs.Fatal("read config dir err:%v", err)
	}
	for _, v := range dir {
		configFile := path.Join(configDir, v.Name())
		if v.Name() == gameConfig {
			readGameConfig(configFile)
		}
		if v.Name() == starshipConfig {
			readStarshipConfig(configFile)
		}
		if v.Name() == buildConfig {
			readBuildConfig(configFile)
		}
		if v.Name() == materialConfig {
			readMaterialConfig(configFile)
		}
		if v.Name() == resourceStarConfig {
			readResourceStarConfig(configFile)
		}
		if v.Name() == activityConfig {
			readActivityConfig(configFile)
		}
		if v.Name() == servers {
			readServersConfig(configFile)
		}
	}
}

func readActivityConfig(configFile string) {
	var config = make(map[string]ConfigValue)
	v := viper.New()
	v.SetConfigFile(configFile)
	v.WatchConfig()
	v.OnConfigChange(func(in fsnotify.Event) {
		log.Println("gameConfig配置文件被修改了")
		err := v.Unmarshal(&config)
		if err != nil {
			panic(fmt.Errorf("gameConfig Unmarshal change config data,err:%v\n", err))
			return
		}
		Conf.ActivityConfig = config
	})
	err := v.ReadInConfig()
	if err != nil {
		panic(fmt.Errorf("gameConfig读取配置文件错误,err:%v\n", err))
		return
	}
	//解析
	err = v.Unmarshal(&config)
	if err != nil {
		panic(fmt.Errorf("gameConfig Unmarshal config data,err:%v\n", err))
		return
	}
	Conf.ActivityConfig = config
}

func readResourceStarConfig(configFile string) {
	var config = make(map[string]ConfigValue)
	v := viper.New()
	v.SetConfigFile(configFile)
	v.WatchConfig()
	v.OnConfigChange(func(in fsnotify.Event) {
		log.Println("gameConfig配置文件被修改了")
		err := v.Unmarshal(&config)
		if err != nil {
			panic(fmt.Errorf("gameConfig Unmarshal change config data,err:%v\n", err))
			return
		}
		Conf.ResourceStarConfig = config
	})
	err := v.ReadInConfig()
	if err != nil {
		panic(fmt.Errorf("gameConfig读取配置文件错误,err:%v\n", err))
		return
	}
	//解析
	err = v.Unmarshal(&config)
	if err != nil {
		panic(fmt.Errorf("gameConfig Unmarshal config data,err:%v\n", err))
		return
	}
	Conf.ResourceStarConfig = config
}

func readMaterialConfig(configFile string) {
	var gameConfig = make(map[string]ConfigValue)
	v := viper.New()
	v.SetConfigFile(configFile)
	v.WatchConfig()
	v.OnConfigChange(func(in fsnotify.Event) {
		log.Println("gameConfig配置文件被修改了")
		err := v.Unmarshal(&gameConfig)
		if err != nil {
			panic(fmt.Errorf("gameConfig Unmarshal change config data,err:%v\n", err))
			return
		}
		Conf.MaterialConfig = gameConfig
	})
	err := v.ReadInConfig()
	if err != nil {
		panic(fmt.Errorf("gameConfig读取配置文件错误,err:%v\n", err))
		return
	}
	//解析
	err = v.Unmarshal(&gameConfig)
	if err != nil {
		panic(fmt.Errorf("gameConfig Unmarshal config data,err:%v\n", err))
		return
	}
	Conf.MaterialConfig = gameConfig
}

func readBuildConfig(configFile string) {
	var gameConfig = make(map[string]ConfigValue)
	v := viper.New()
	v.SetConfigFile(configFile)
	v.WatchConfig()
	v.OnConfigChange(func(in fsnotify.Event) {
		log.Println("gameConfig配置文件被修改了")
		err := v.Unmarshal(&gameConfig)
		if err != nil {
			panic(fmt.Errorf("gameConfig Unmarshal change config data,err:%v\n", err))
			return
		}
		Conf.BuildConfig = gameConfig
	})
	err := v.ReadInConfig()
	if err != nil {
		panic(fmt.Errorf("gameConfig读取配置文件错误,err:%v\n", err))
		return
	}
	//解析
	err = v.Unmarshal(&gameConfig)
	if err != nil {
		panic(fmt.Errorf("gameConfig Unmarshal config data,err:%v\n", err))
		return
	}
	Conf.BuildConfig = gameConfig
}

func readStarshipConfig(configFile string) {
	var gameConfig = make(map[string]ConfigValue)
	v := viper.New()
	v.SetConfigFile(configFile)
	v.WatchConfig()
	v.OnConfigChange(func(in fsnotify.Event) {
		log.Println("gameConfig配置文件被修改了")
		err := v.Unmarshal(&gameConfig)
		if err != nil {
			panic(fmt.Errorf("gameConfig Unmarshal change config data,err:%v\n", err))
			return
		}
		Conf.StarshipConfig = gameConfig
	})
	err := v.ReadInConfig()
	if err != nil {
		panic(fmt.Errorf("gameConfig读取配置文件错误,err:%v\n", err))
		return
	}
	//解析
	err = v.Unmarshal(&gameConfig)
	if err != nil {
		panic(fmt.Errorf("gameConfig Unmarshal config data,err:%v\n", err))
		return
	}
	Conf.StarshipConfig = gameConfig
}

func readServersConfig(configFile string) {
	var serversConfig ServersConf
	v := viper.New()
	v.SetConfigFile(configFile)
	v.WatchConfig()
	v.OnConfigChange(func(in fsnotify.Event) {
		log.Println("serversConfig配置文件被修改了")
		err := v.Unmarshal(&serversConfig)
		if err != nil {
			panic(fmt.Errorf("serversConfig Unmarshal change config data,err:%v\n", err))
			return
		}
		Conf.ServersConf = serversConfig
	})
	err := v.ReadInConfig()
	if err != nil {
		panic(fmt.Errorf("serversConfig读取配置文件错误,err:%v\n", err))
		return
	}
	//解析
	err = v.Unmarshal(&serversConfig)
	if err != nil {
		panic(fmt.Errorf("serversConfig Unmarshal config data,err:%v\n", err))
		return
	}
	Conf.ServersConf = serversConfig
	typeServersConfig()
}

func typeServersConfig() {
	if len(Conf.ServersConf.Servers) > 0 {
		if Conf.ServersConf.TypeServer == nil {
			Conf.ServersConf.TypeServer = make(map[string][]*ServersConfig)
		}
		for _, v := range Conf.ServersConf.Servers {
			if Conf.ServersConf.TypeServer[v.ServerType] == nil {
				Conf.ServersConf.TypeServer[v.ServerType] = make([]*ServersConfig, 0)
			}
			Conf.ServersConf.TypeServer[v.ServerType] = append(Conf.ServersConf.TypeServer[v.ServerType], v)
		}
	}
}

func readGameConfig(configFile string) {
	var config = make(map[string]map[string]any)
	v := viper.New()
	v.SetConfigFile(configFile)
	v.WatchConfig()
	v.OnConfigChange(func(in fsnotify.Event) {
		log.Println("gameConfig配置文件被修改了")
		err := v.Unmarshal(&config)
		if err != nil {
			panic(fmt.Errorf("gameConfig Unmarshal change config data,err:%v\n", err))
			return
		}
		Conf.GameConfig = config
	})
	err := v.ReadInConfig()
	if err != nil {
		panic(fmt.Errorf("gameConfig读取配置文件错误,err:%v\n", err))
		return
	}
	//解析
	err = v.Unmarshal(&config)
	if err != nil {
		panic(fmt.Errorf("gameConfig Unmarshal config data,err:%v\n", err))
		return
	}
	Conf.GameConfig = config
	////var gameConfig = make(map[string]GameConfigValue)
	////v := viper.New()
	////v.SetConfigFile(configFile)
	////v.WatchConfig()
	////v.OnConfigChange(func(in fsnotify.Event) {
	////	log.Println("gameConfig配置文件被修改了")
	////	err := v.Unmarshal(&gameConfig)
	////	if err != nil {
	////		panic(fmt.Errorf("gameConfig Unmarshal change config data,err:%v\n", err))
	////		return
	////	}
	////	Conf.GameConfig = gameConfig
	////})
	////err := v.ReadInConfig()
	////if err != nil {
	////	panic(fmt.Errorf("gameConfig读取配置文件错误,err:%v\n", err))
	////	return
	////}
	//////解析
	////err = v.Unmarshal(&gameConfig)
	////if err != nil {
	////	panic(fmt.Errorf("gameConfig Unmarshal config data,err:%v\n", err))
	////	return
	////}
	////Conf.GameConfig = gameConfig
	//file, err := os.Open(configFile)
	//if err != nil {
	//	panic(err)
	//}
	//defer file.Close()
	//data, err := io.ReadAll(file)
	//if err != nil {
	//	panic(err)
	//}
	//var gc map[string]GameConfigValue
	//err = json.Unmarshal(data, &gc)
	//if err != nil {
	//	panic(err)
	//}
	//Conf.GameConfig = gc
}

func (c *Config) GetConnector(serverId string) *ConnectorConfig {
	for _, v := range c.ServersConf.Connector {
		if v.ID == serverId {
			return v
		}
	}
	return nil
}

func (c *Config) GetConnectorByServerType(serverType string) *ConnectorConfig {
	for _, v := range c.ServersConf.Connector {
		if v.ServerType == serverType {
			return v
		}
	}
	return nil
}
func (c *Config) GetFrontGameConfig() map[string]any {
	//result := make(map[string]any)
	//for k, v := range c.GameConfig {
	//	if v.Backend {
	//		result[k] = v.Value
	//	}
	//}
	//return result
	result := make(map[string]any)
	for k, v := range c.GameConfig {
		value, ok := v["value"]
		backend := false
		_, exist := v["backend"]
		if exist {
			backend = v["backend"].(bool)
		}
		if ok && !backend {
			result[k] = value
		}
	}
	return result
}

func (c *Config) GetFrontStarshipConfig() map[string]any {
	result := make(map[string]any)
	for k, v := range c.StarshipConfig {
		if v.Backend {
			result[k] = v.Value
		}
	}
	return result
}

func (c *Config) GetFrontBuildConfig() map[string]any {
	result := make(map[string]any)
	for k, v := range c.BuildConfig {
		if v.Backend {
			result[k] = v.Value
		}
	}
	return result
}

func (c *Config) GetFrontMaterialConfig() map[string]any {
	result := make(map[string]any)
	for k, v := range c.MaterialConfig {
		if v.Backend {
			result[k] = v.Value
		}
	}
	return result
}

func (c *Config) GetFrontResourceStarConfig() map[string]any {
	result := make(map[string]any)
	for k, v := range c.ResourceStarConfig {
		if v.Backend {
			result[k] = v.Value
		}
	}
	return result
}
